#[cfg(feature = "ssr")]
use crate::base::{Error, Result};
use crate::{
    prelude::{
        report::{DisplayCols, Unit},
        ColumnRange, DataType, FliterItems,
    },
    structs::{FieldProps, FieldType},
};
use edit_props::EditProps;
use options::Options;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use table_props::TableProps;
pub mod edit_props;
pub mod options;
pub mod table_props;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExportQueryParams {
    pub conf_name: String,
    pub display_cols: DisplayCols,
    pub filters: Option<String>,
    pub orders: Option<String>,
    pub user_id: u32,
    pub menu_id: u32,
}
impl ExportQueryParams {
    pub fn new(
        conf_name: String,
        display_cols: DisplayCols,
        filters: Option<String>,
        orders: Option<String>,
        user_id: u32,
        menu_id: u32,
    ) -> Self {
        Self {
            conf_name,
            display_cols,
            filters: filters,
            orders: orders,
            user_id,
            menu_id,
        }
    }
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExportReptParams {
    pub rept_name: String,
    pub params: Vec<(String, String)>,
    pub filters: Option<String>,
    pub orders: Option<String>,
    pub display_cols: DisplayCols,
    pub group_index: u8,
    #[serde(default)]
    pub drill_down_requ: Vec<(u8, Value)>,
    pub extra_where: Option<String>,
    pub user_id: u32,
    pub perm_id: u32,
    pub one_sheet_on_file: bool,
    pub rebuild: bool,
}
impl ExportReptParams {
    pub fn new(
        rept_name: String,
        params: Vec<(String, String)>,
        filters: Option<String>,
        orders: Option<String>,
        display_cols: DisplayCols,
        group_index: u8,
        drill_down_requ: Vec<(u8, Value)>,
        extra_where: Option<String>,
        user_id: u32,
        perm_id: u32,
        one_sheet_on_file: bool,
        rebuild: bool,
    ) -> Self {
        Self {
            rept_name,
            params,
            filters: filters,
            orders: orders,
            display_cols,
            group_index,
            drill_down_requ,
            extra_where,
            user_id,
            perm_id,
            one_sheet_on_file,
            rebuild,
        }
    }
}
/** 列 */
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Column {
    /** 名称 */
    #[serde(default)]
    pub name: Option<String>,
    /** 标题 */
    #[serde(default)]
    pub title: Option<String>,
    /** 查看列所需要的权限类型，用于根据权限控制用户是否可以查看 */
    #[serde(default)]
    pub popedom_types: Vec<ColumnRange>,
    /** 数据类型 */
    #[serde(default)]
    pub data_type: DataType,
    /** 字段类型 */
    #[serde(skip)]
    pub field_type: FieldType,
    /** 是否主键 */
    #[serde(default)]
    pub is_pk: bool,
    /** 是否自动增长 */
    #[serde(default)]
    pub is_auto_incr: bool,
    /** 是否可空 */
    #[serde(default)]
    pub is_null: bool,
    /** 是否可空 */
    #[serde(default = "unit_default")]
    pub unit: Unit,
    /** 子列 */
    #[serde(default)]
    pub children: Vec<Column>,
    /** 列表属性 */
    #[serde(default)]
    pub list_props: Option<TableProps>,
    /** 编辑属性 */
    #[serde(default)]
    pub edit_props: Option<EditProps>,
    /** 字典数据列名称 */
    #[serde(default)]
    pub dict_col_name: Option<String>,
    #[serde(default)]
    pub default_filter: Option<FliterItems>,
}
fn unit_default() -> Unit {
    Unit::Yuan
}
#[cfg(feature = "ssr")]
impl Column {
    pub(crate) async fn parse(&mut self, table_name: &str, fps: &Vec<FieldProps>) -> Result<()> {
        if self.title.is_none() && self.name.is_none() {
            return Err(Error::Conf("Column的title和name不能同时为空".to_string()));
        }
        let col_desc = if let Some(title) = &self.title {
            title.as_str()
        } else {
            self.name.as_deref().unwrap()
        };
        if self.children.is_empty() {
            if self.name.is_none() {
                return Err(Error::Conf(format!(
                    "Column:{col_desc}为叶节点,name不能为空",
                )));
            }
            let mut is_ok = false;
            for f in fps.iter() {
                if Some(f.name.as_str()) == self.name.as_deref() {
                    self.field_type = f.field_type.clone();
                    self.is_pk = f.is_pk;
                    self.is_auto_incr = f.is_auto_incr;
                    self.is_null = f.is_null;
                    self.data_type = f.field_type.clone().into();
                    is_ok = true;
                    if let Some(eps) = self.edit_props.as_mut() {
                        eps.parse(f).await.or_else(|err| {
                            Err(Error::Conf(format!("Column:{col_desc}错误,{}", err)))
                        })?;
                    }
                    if let Some(opts) = self.edit_props.as_ref().and_then(|e| e.options.as_ref()) {
                        if !matches!(*opts, Options::Array(_)) {
                            if let Some(lps) = self.list_props.as_ref() {
                                if lps.display {
                                    self.dict_col_name =
                                        Some(format!("{}__dict", self.name.as_deref().unwrap()));
                                }
                            }
                        };
                    }
                }
            }
            if !is_ok {
                return Err(Error::Conf(format!(
                    "field_props中配置字段名{col_desc}在实体类{}不存在",
                    table_name
                )));
            }
        } else {
            for c in self.children.iter_mut() {
                if let Err(err) = Box::pin(c.parse(table_name, fps)).await {
                    return Err(err);
                }
            }
        }
        Ok(())
    }
}
#[derive(Debug, Copy, PartialEq, Eq, Clone, Serialize)]
pub enum Align {
    Left,
    Right,
    Center,
}
impl Default for Align {
    fn default() -> Self {
        Align::Left
    }
}
impl<'de> Deserialize<'de> for Align {
    fn deserialize<D>(deserializer: D) -> std::result::Result<Align, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        match s.to_lowercase().as_str() {
            "left" => Ok(Align::Left),
            "right" => Ok(Align::Right),
            "center" => Ok(Align::Center),
            _ => Err(serde::de::Error::custom(format!("未知的Align: {}", s))),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Condition {
    Bool(bool),
    Exp(String),
}

impl Default for Condition {
    fn default() -> Self {
        Condition::Bool(false)
    }
}

#[derive(Debug, Copy, PartialEq, Eq, Clone, Serialize, strum::Display)]
pub enum ControlType {
    TextInput,
    IntegerInput,
    DecimalInput,
    AlphaInput,
    AlphanumInput,
    Year,
    Quarter,
    Month,
    Date,
    Time,
    Datetime,
    Select,
    TreeSelect,
    Checkbox,
    CheckboxGroup,
    RadioGroup,
    Search,
    Textarea,
}

impl Default for ControlType {
    fn default() -> Self {
        ControlType::TextInput
    }
}
impl<'de> Deserialize<'de> for ControlType {
    fn deserialize<D>(deserializer: D) -> std::result::Result<ControlType, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        match s.to_lowercase().as_str() {
            "textinput" | "text" => Ok(ControlType::TextInput),
            "integerinput" | "integer" | "int"=> Ok(ControlType::IntegerInput),
            "decimalinput" | "decimal" | "dec" | "float" => Ok(ControlType::DecimalInput),
            "alphainput" | "alpha" => Ok(ControlType::AlphaInput),
            "alphanuminput" | "alphanum" => Ok(ControlType::AlphanumInput),
            "year" => Ok(ControlType::Year),
            "quarter" => Ok(ControlType::Quarter),
            "month" => Ok(ControlType::Month),
            "date" => Ok(ControlType::Date),
            "time" => Ok(ControlType::Time),
            "datetime" => Ok(ControlType::Datetime),
            "select" => Ok(ControlType::Select),
            "treeselect" => Ok(ControlType::TreeSelect),
            "checkbox" => Ok(ControlType::Checkbox),
            "checkboxgroup" => Ok(ControlType::CheckboxGroup),
            "radiogroup" => Ok(ControlType::RadioGroup),
            "search" => Ok(ControlType::Search),
            "textarea" => Ok(ControlType::Textarea),
            _ => Err(serde::de::Error::custom(format!(
                "未知的ControlType: {}",
                s
            ))),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize)]
pub enum Size {
    LG,
    MD,
    SM,
    XS,
}
impl Default for Size {
    fn default() -> Self {
        Size::SM
    }
}
impl Size {
    pub fn to_class(&self, prefix: &str) -> String {
        let s = match self {
            Size::LG => "lg",
            Size::MD => "md",
            Size::SM => "sm",
            Size::XS => "xs",
        };
        format!("{}-{}", prefix, s)
    }
}
impl<'de> Deserialize<'de> for Size {
    fn deserialize<D>(deserializer: D) -> std::result::Result<Size, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        match s.to_lowercase().as_str() {
            "lg" => Ok(Size::LG),
            "md" => Ok(Size::MD),
            "sm" => Ok(Size::SM),
            "xs" => Ok(Size::XS),
            _ => Err(serde::de::Error::custom(format!("未知的Size: {}", s))),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum VerifyRule {
    /**范围（最小值，最大值），对于字符串是最小长度和最大长度 */
    Range(isize, isize),
    /** 规则表达式（regex.yaml中配置的名称） */
    Regex(String),
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct KvItem {
    pub label: String,
    pub value: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct TreeNode {
    /** 键值 */
    pub key: String,
    /** 标题 */
    pub title: String,
    /** 所属键值 */
    pub parent_key: Option<String>,
}
impl TreeNode {
    pub fn new(key: impl AsRef<str>, title: impl AsRef<str>, parent_key: Option<String>) -> Self {
        Self {
            key: key.as_ref().to_string(),
            title: title.as_ref().to_string(),
            parent_key,
        }
    }
}
impl From<KvItem> for TreeNode {
    fn from(item: KvItem) -> Self {
        Self {
            key: item.value,
            title: item.label,
            parent_key: None,
        }
    }
}
impl From<String> for TreeNode {
    fn from(items: String) -> Self {
        Self {
            key: items.clone(),
            title: items.clone(),
            parent_key: None,
        }
    }
}
pub(crate) fn has_duplicates<T: PartialEq + Eq + std::hash::Hash>(slice: &[T]) -> bool {
    // 使用HashSet存储已经出现的元素
    let mut seen = std::collections::HashSet::new();
    // 遍历切片，检查是否有元素已经存在于HashSet中
    for item in slice {
        if seen.contains(item) {
            return true; // 如果找到重复，返回true
        }
        seen.insert(item); // 否则，将元素插入HashSet中
    }
    false
}
